
#include "mainwindow.h"
#include "deal_http_post_details.h"
#include "download_task_thread.h"
#include "goods_widget.h"
#include "image_provider.h"
#include "JlCompress.h"
#include <QProcess>
#include <QMessageBox>
#include <iostream>
#include "unzip_thread.h"

#define UNIT_KB	1024			//KB
#define UNIT_MB 1024*1024		//MB
#define UNIT_GB 1024*1024*1024	//GB

#define TIME_INTERVAL 300		//0.3s

MainWindow::MainWindow(QWidget *parent)
        : QWidget(parent)
{
    ui.setupUi(this);
    setFixedSize(1024, 600);
    // 设置窗口无边框
    setWindowFlags(Qt::FramelessWindowHint);
    setWindowIcon(QIcon(":/resources/logo.png"));
    initUi();
    connect(&DealHttpPostDetails::instance(),&DealHttpPostDetails::signalUpdateVersionCheck,this,&MainWindow::updateVersionCheck);
    connect(&DownloadTaskThread::instance(),&DownloadTaskThread::sig_download,this,&MainWindow::download);
    connect(&DealHttpPostDetails::instance(),&DealHttpPostDetails::signalGoods,this,&MainWindow::showGoods);
    connect(&DealHttpPostDetails::instance(),&DealHttpPostDetails::signalTextNews,this,&MainWindow::showTextNews);
    connect(&DealHttpPostDetails::instance(),&DealHttpPostDetails::signalPicNews,this,&MainWindow::showPicNews);
    image_provider_ = new ImageProvider(QQmlImageProviderBase::Image);

    connect(ui.listWidget,&QListWidget::itemClicked,this,&MainWindow::itemClicked);
    timer.start(2000);
}

MainWindow::~MainWindow()
{
    DownloadTaskThread::instance().stop();
    DownloadTaskThread::instance().quit();
    DownloadTaskThread::instance().wait();

    UnZipThread::instance().quit();
    UnZipThread::instance().wait();

    delete image_provider_;
    for(auto &goodWidget:good_widgets_)
    {
        delete goodWidget;
    }
}

void MainWindow::itemClicked(QListWidgetItem *item)
{
    ui.plainTextEdit->setPlainText(m_versionMap[item->text()].second);
}

void MainWindow::initUi()
{
    ui.widget_news_pic->setFixedSize(460,300);
    downLoadPage(false);
    getLocalVersion();
    DealHttpPostDetails::instance().versionCheck();
    DealHttpPostDetails::instance().getGoods();
    DealHttpPostDetails::instance().getPicNews();
    DealHttpPostDetails::instance().getTextNews();
    ui.progressBar->setValue(0);
    connect(&UnZipThread::instance(), SIGNAL(sig_unzipFinished(const bool&)), this, SLOT(unzipFinished(const bool&)));

    ui.plainTextEdit->setReadOnly(true);
    ui.plainTextEdit->setContextMenuPolicy(Qt::ContextMenuPolicy::NoContextMenu);

    ui.btn_home->setIcon(QIcon(":/resources/home.png"));
    //设置控件的布局方向，默认是Qt::LeftToRight，可设置Qt::RightToLeft 从右往左
    ui.btn_home->setLayoutDirection(Qt::LeftToRight);

    ui.btn_shops->setIcon(QIcon(":/resources/shopping_mall.png"));
    //设置控件的布局方向，默认是Qt::LeftToRight，可设置Qt::RightToLeft 从右往左
    ui.btn_shops->setLayoutDirection(Qt::LeftToRight);

    ui.btn_mini->setIcon(QIcon(":/resources/minimum.png"));
    //设置控件的布局方向，默认是Qt::LeftToRight，可设置Qt::RightToLeft 从右往左
    ui.btn_mini->setLayoutDirection(Qt::LeftToRight);

    ui.btn_close->setIcon(QIcon(":/resources/close.png"));
    //设置控件的布局方向，默认是Qt::LeftToRight，可设置Qt::RightToLeft 从右往左
    ui.btn_close->setLayoutDirection(Qt::LeftToRight);
}

void MainWindow::downLoadPage(const bool & isDownload)
{
    if(isDownload)
    {
        ui.frame->setVisible(isDownload);
    }
    else
    {
        ui.frame->setVisible(isDownload);
    }
}

void MainWindow::getLocalVersion()
{
    QFile file("data/version.dat");
    file.open(QIODevice::ReadOnly);
    m_version = file.readLine();
    std::cout << m_version.toStdString() << std::endl;
    file.close();
}

void MainWindow::download(const QString &name)
{
    QString downloadUrl = "";
    downloadUrl = m_versionMap[name].first;
    UnZipThread::instance().setName(name);
    if (m_downloadManager == NULL)
    {
        m_downloadManager = new DownloadManager(this);
        connect(m_downloadManager , SIGNAL(signalDownloadProcess(qint64, qint64)), this, SLOT(onDownloadProcess(qint64, qint64)));
        connect(m_downloadManager, SIGNAL(signalReplyFinished(int)), this, SLOT(onReplyFinished(int)));
    }

    QString url = m_downloadManager->getDownloadUrl();
    if (url != downloadUrl)
    {
        m_downloadManager->reset();
    }
    m_downloadManager->setDownInto(true);
    m_downloadManager->downloadFile(downloadUrl, "./update.zip");
    m_timeRecord.start();
    m_timeInterval = 0;
    ui.label_download_status->setText(QStringLiteral("正在下载"));
}

void MainWindow::unzipFinished(const bool& isok)
{
    if(!isok)
    {
        ui.label_download_status->setText(QStringLiteral("更新失败，请重新下载"));
    }
    else
    {
        ui.label_download_status->setText(QStringLiteral("更新成功"));
        ui.label_remain_time->setText("0s");
        ui.label_speed->setText("0 KB/S");
        getLocalVersion();
        DealHttpPostDetails::instance().versionCheck();
        DownloadTaskThread::instance().downFinished();
    }
}

void MainWindow::onStopDownload()
{
    ui.label_download_status->setText(QStringLiteral("停止下载"));
    if (m_downloadManager != NULL)
    {
        m_downloadManager->stopDownload();
    }
    ui.label_speed->setText("0 KB/S");
    ui.label_remain_time->setText("0s");
}

// 关闭下载;
void MainWindow::onCloseDownload()
{
    m_downloadManager->closeDownload();
    ui.progressBar->setValue(0);
    ui.label_speed->setText("0 KB/S");
    ui.label_remain_time->setText("0s");
    ui.label_download_status->setText(QStringLiteral("关闭下载"));
    ui.label_current_download->setText("0 B");
    ui.label_file_size->setText("0 B");
}

// 更新下载进度;
void MainWindow::onDownloadProcess(qint64 bytesReceived, qint64 bytesTotal)
{
    // 更新进度条;
    ui.progressBar->setMaximum(bytesTotal);
    ui.progressBar->setValue(bytesReceived);

    m_intervalDownload += bytesReceived - m_currentDownload;
    m_currentDownload = bytesReceived;

    uint timeNow = m_timeRecord.elapsed();

    // 超过0.3s更新一次速度;
    if (timeNow - m_timeInterval > TIME_INTERVAL)
    {
        qint64 ispeed = m_intervalDownload * 1000 / (timeNow - m_timeInterval);
        QString strSpeed = transformUnit(ispeed, true);
        ui.label_speed->setText(strSpeed);
        // 剩余时间;
        qint64 timeRemain = 999999;
        if(ispeed != 0)
        {
            timeRemain = (bytesTotal - bytesReceived) / ispeed;
        }
        ui.label_remain_time->setText(transformTime(timeRemain));
        ui.label_current_download->setText(transformUnit(m_currentDownload));
        ui.label_file_size->setText(transformUnit(bytesTotal));

        m_intervalDownload = 0;
        m_timeInterval = timeNow;
    }
    if(bytesTotal == bytesReceived)
    {
        ui.label_download_status->setText(QStringLiteral("下载完成,请等待解压"));
        ui.label_remain_time->setText("0s");
        ui.label_speed->setText("0 KB/S");
        QProcess p;
        p.execute("taskkill /im edi_cache.exe /f");
        p.execute("taskkill /im edi_server.exe /f");
        p.execute("taskkill /im EDI.exe /f");
        p.waitForFinished();
        UnZipThread::instance().start();
    }
    update();
}

void MainWindow::onReplyFinished(int statusCode)
{
    /*if (statusCode >= 200 && statusCode < 400)
    {
        std::cout << "Download Failed" << std::endl;
    }
    else
    {
        std::cout << "Download Success" << std::endl;
    }*/
}

// 转换单位;
QString MainWindow::transformUnit(qint64 bytes , bool isSpeed)
{
    QString strUnit = " B";
    if (bytes <= 0)
    {
        bytes = 0;
    }
    else if (bytes < UNIT_KB)
    {
    }
    else if (bytes < UNIT_MB)
    {
        bytes /= UNIT_KB;
        strUnit = " KB";
    }
    else if (bytes < UNIT_GB)
    {
        bytes /= UNIT_MB;
        strUnit = " MB";
    }
    else if (bytes > UNIT_GB)
    {
        bytes /= UNIT_GB;
        strUnit = " GB";
    }

    if (isSpeed)
    {
        strUnit += "/S";
    }
    return QString("%1%2").arg(bytes).arg(strUnit);
}

QString MainWindow::transformTime(qint64 seconds)
{
    QString strValue;
    QString strSpacing(" ");
    if (seconds <= 0)
    {
        strValue = QString("%1s").arg(0);
    }
    else if (seconds < 60)
    {
        strValue = QString("%1s").arg(seconds);
    }
    else if (seconds < 60 * 60)
    {
        int nMinute = seconds / 60;
        int nSecond = seconds - nMinute * 60;

        strValue = QString("%1m").arg(nMinute);

        if (nSecond > 0)
            strValue += strSpacing + QString("%1s").arg(nSecond);
    }
    else if (seconds < 60 * 60 * 24)
    {
        int nHour = seconds / (60 * 60);
        int nMinute = (seconds - nHour * 60 * 60) / 60;
        int nSecond = seconds - nHour * 60 * 60 - nMinute * 60;

        strValue = QString("%1h").arg(nHour);

        if (nMinute > 0)
            strValue += strSpacing + QString("%1m").arg(nMinute);

        if (nSecond > 0)
            strValue += strSpacing + QString("%1s").arg(nSecond);
    }
    else
    {
        int nDay = seconds / (60 * 60 * 24);
        int nHour = (seconds - nDay * 60 * 60 * 24) / (60 * 60);
        int nMinute = (seconds - nDay * 60 * 60 * 24 - nHour * 60 * 60) / 60;
        int nSecond = seconds - nDay * 60 * 60 * 24 - nHour * 60 * 60 - nMinute * 60;

        strValue = QString("%1d").arg(nDay);

        if (nHour > 0)
            strValue += strSpacing + QString("%1h").arg(nHour);

        if (nMinute > 0)
            strValue += strSpacing + QString("%1m").arg(nMinute);

        if (nSecond > 0)
            strValue += strSpacing + QString("%1s").arg(nSecond);
    }

    return strValue;
}

void MainWindow::updateVersionCheck(const QJsonArray &array)
{
    m_list.clear();
    m_versionMap.clear();
    ui.listWidget->clear();
    for(const auto & ver : array)
    {
        QString version = ver.toObject()["name"].toString();
        QString filename = ver.toObject()["file_path"].toString();
        QString describe = ver.toObject()["describe"].toString();
        if(checkNeedUpdate(version))
        {
            m_list << version;
            m_versionMap[version] = QPair<QString,QString>(filename,describe);
        }
    }

    std::reverse(m_list.begin(),m_list.end());

    for(int i = 0 ; i < m_list.size() ;i++)
    {
        ui.listWidget->addItem(m_list[i]);
    }

    if(m_list.size()>0)
    {
        ui.plainTextEdit->setPlainText(m_versionMap[m_list[0]].second);
    }

    if(!m_list.isEmpty())
    {
        ui.btn_enter->setText("Enter(Update)");
    }
    else
    {
        ui.btn_enter->setText("Enter");
    }
}

void MainWindow::showGoods(const QJsonObject &obj)
{
    for(auto & goodWidget : good_widgets_)
    {
        delete goodWidget;
    }
    good_widgets_.clear();
    if(obj.contains("results"))
    {
        QJsonArray array = obj["results"].toArray();
        for(const auto &oo : array)
        {
            QJsonObject goodObj = oo.toObject();
            auto name = goodObj["commodity_name"].toString();
            double price = goodObj["commodity_price"].toDouble();
            auto imagePath = goodObj["thumbnail_picture"].toString();
            QSize size;
            auto image = image_provider_->requestImage(imagePath,&size,size);
            auto *widget = new GoodsWidget();
            widget->setFixedSize(185,260);
            widget->setName(name);
            widget->setPrice(QString::number(price,'f',2));
            widget->setPic(image,110,120);
            good_widgets_.push_back(widget);
        }
    }
    int row = 0;
    int i = 0;
    for(const auto &goodWidget : good_widgets_)
    {
        if(i==5)
        {
            row++;
            i=0;
        }
        ui.goodsLayout->addWidget(goodWidget,row,i);
        i++;
    }
}

bool MainWindow::checkNeedUpdate(const QString &version)
{
    if(version == m_version)
    {
        return false;
    }
    if(m_version.split(".").size() != version.split(".").size() || m_version.split(".").size() < 3)
    {
        return false;
    }
    auto strList1 = m_version.split(".");
    auto strList2 = version.split(".");
    for (int i = 0; i < strList1.size(); ++i)
    {
        int mVer = strList1[i].toInt();
        int newVer = strList2[i].toInt();
        if (mVer == newVer)
        {
            continue;
        }
        return newVer > mVer;
    }
    return false;
}

void MainWindow::onStartDownload()
{
    DownloadTaskThread::instance().setTask(m_list);
    DownloadTaskThread::instance().start();
}

void MainWindow::onCancelDownload()
{
    close();
}

void MainWindow::settings()
{

}

void MainWindow::on_btn_enter_clicked()
{
    if(m_list.isEmpty())
    {
        QString updatePath = QApplication::applicationDirPath()+"/EDI.exe";
        QStringList updateArgs;
        QProcess::startDetached(updatePath, updateArgs);
        quick_exit(0);
    }
    else if(m_first)
    {
        if(m_big_version_)
        {
            QString msg = "当前版本过低，请至官网下载最新版本:<br/><a href='https://chipslightai.com/'>南京星火技术有限公司</a>";
            QMessageBox::about(this,"tip",msg);
            return;
        }

        auto ret = QMessageBox::question(this,"tip","发现新版本，是否更新?",QMessageBox::Yes | QMessageBox::No);
        if(ret == QMessageBox::Yes)
        {
            downLoadPage(true);
            m_first = false;
            QProcess p;
            p.execute("taskkill /im edi_cache.exe /f");
            p.execute("taskkill /im edi_server.exe /f");
            p.execute("taskkill /im EDI.exe /f");
            p.waitForFinished();
            onStartDownload();
        }
    }
}

void MainWindow::on_btn_home_clicked()
{
    ui.stackedWidget->setCurrentWidget(ui.page_version);
}

void MainWindow::on_btn_shops_clicked()
{
    ui.stackedWidget->setCurrentWidget(ui.page_shops);
}

void MainWindow::on_btn_mini_clicked()
{
    showMinimized();
}

void MainWindow::on_btn_close_clicked()
{
    close();
}

void MainWindow::mouseMoveEvent(QMouseEvent *event)
{
    if ((event->buttons() == Qt::LeftButton) && left_button_pressed_)
    {
        move(event->globalPos() - last_position_);
    }
}

void MainWindow::mouseReleaseEvent(QMouseEvent *)
{
    left_button_pressed_ = false;
}

void MainWindow::mousePressEvent(QMouseEvent *event)
{
    if (event->buttons() == Qt::LeftButton) {
        left_button_pressed_ = true;
        last_position_ = event->globalPos() - pos();
    }
}

void MainWindow::showTextNews(const QJsonObject &obj)
{
    if(obj.contains("results"))
    {
        QJsonArray array = obj["results"].toArray();
        if(array.isEmpty())
        {
            showDefaultTextNew();
        }
        else
        {
            QString title = array[0].toObject()["title"].toString();
            QString content = array[0].toObject()["content"].toString();
            ui.widget_relevant_information->setTitle(title);
            ui.widget_relevant_information->setContent(content);
        }
    }
    else
    {
        showDefaultTextNew();
    }
}

void MainWindow::showDefaultTextNew()
{
    ui.widget_relevant_information->setTitle("");
    ui.widget_relevant_information->setContent("");
}

void MainWindow::showDefaultPicNew1()
{
    ui.widget_latest_news->setPic(":/resources/conference.jpg");
    ui.widget_latest_news->setDate("1212");
    ui.widget_latest_news->setMask("3434");
}

void MainWindow::showDefaultPicNew2()
{
    ui.widget_latest_news2->setPic(":/resources/conference.jpg");
    ui.widget_latest_news2->setDate("1212");
    ui.widget_latest_news2->setMask("3434");
}

void MainWindow::showPicNews(const QJsonObject &obj)
{
    if(obj.contains("results"))
    {
        QJsonArray array = obj["results"].toArray();
        if(array.isEmpty())
        {
            showDefaultPicNew1();
            showDefaultPicNew2();
        }
        else if(array.size() == 1)
        {
            ui.widget_latest_news->setPic(":/resources/conference.jpg");
            ui.widget_latest_news->setDate("1212");
            ui.widget_latest_news->setMask("3434");
            showDefaultPicNew2();
            // ImageProvider
        }
    }
    else
    {
        showDefaultPicNew1();
        showDefaultPicNew2();
    }
}

